#include "StdAfx.h"
#include "SystemTray.h"
#include <afxpriv.h>

IMPLEMENT_DYNAMIC(CSystemTray, CCmdTarget)

CSystemTray::CSystemTray(UINT uID)
{
	memset( &m_nid, 0, sizeof(m_nid));
	m_nid.cbSize = sizeof(m_nid);
	m_nid.uID = uID;		// Never changes after construction

	AfxLoadString(uID, m_nid.szTip, sizeof(m_nid.szTip));
}

CSystemTray::~CSystemTray(void)
{
	SetIcon(0);	//Remove icon from system tray
}

// Call this to receive tray notifications
void CSystemTray::SetNotificationWnd(CWnd* pNotifyWnd, UINT uCbMsg)
{
	ASSERT( pNotifyWnd == NULL || ::IsWindow( pNotifyWnd->GetSafeHwnd()) );
	m_nid.hWnd = pNotifyWnd->GetSafeHwnd();

	ASSERT(uCbMsg == 0 || uCbMsg >= WM_USER);
	m_nid.uCallbackMessage = uCbMsg;
}

// SetIcon functions. To remove icon, call SetIcon(0);
BOOL CSystemTray::SetIcon(UINT uID)
{
	HICON hIcon = NULL;
	if (uID)
	{
//		AfxLoadString( uID, m_nid.szTip, sizeof(m_nid.szTip));
		hIcon = AfxGetApp()->LoadIcon(uID);
	}
	return SetIcon(hIcon, NULL);
}
BOOL CSystemTray::SetIcon(HICON hIcon, LPCSTR lpTip)
{
	UINT msg;
	m_nid.uFlags = 0;
	
	if (hIcon)
	{
		msg = m_nid.hIcon ? NIM_MODIFY : NIM_ADD;
		if (m_nid.hIcon)
		{
			DestroyIcon(m_nid.hIcon);
		}
		m_nid.hIcon = hIcon;
		m_nid.uFlags |= NIF_ICON;
	}else
	{
		if (m_nid.hIcon == NULL)
			return TRUE;	//already deleted
		msg = NIM_DELETE;
	}

	// Use the tip, if any
	if (lpTip)
		_tcsncpy( m_nid.szTip, (const TCHAR*)lpTip, sizeof(m_nid.szTip));
	if (m_nid.szTip[0])
		m_nid.uFlags |= NIF_TIP;

	// Use callback if any
	if (m_nid.uCallbackMessage && m_nid.hWnd)
		m_nid.uFlags |= NIF_MESSAGE;

	// Do it
	BOOL bRet = Shell_NotifyIcon( msg, &m_nid);
	if (msg == NIM_DELETE || !bRet)
		m_nid.hIcon = NULL;	// Failed

	return bRet;
}

BOOL CSystemTray::SetTips(LPCSTR lpTip)
{
	if (lpTip == NULL)
		return FALSE;
	m_nid.uFlags = NIF_TIP;
	_tcsncpy( m_nid.szTip, (const TCHAR*)lpTip, sizeof(m_nid.szTip));
	
	return Shell_NotifyIcon( NIM_MODIFY, &m_nid);
}

// Move to the parent
LRESULT CSystemTray::OnTrayNotification(WPARAM uID, LPARAM lEvent)
{
	if (uID != m_nid.uID || (lEvent != WM_RBUTTONUP && lEvent != WM_LBUTTONDBLCLK))
		return 0;

	// If there's a resource menu with the same ID as the icon, use it as the riht-button popup menu.
	// SBSystemTray will interprets the first item in the menu as the default cocmmand for M_LBUTTONDBCLK
	CMenu menu;
	if (!menu.LoadMenu(m_nid.uID))
		return 0;
	CMenu *pSubMenu = menu.GetSubMenu(0);
	if (!pSubMenu)
		return 0;

	if (lEvent == WM_RBUTTONUP)
	{
		// Make first menu item the default (bold font)
		::SetMenuDefaultItem( pSubMenu->m_hMenu, 0, TRUE);

		// Display the menu at the current mouse location.
		// There's a 'bug' (Microsoft calls it a feature) in Windows 95 that requires calling SetForegroundWindow.
		// To find out more, search for Q135788 in MSDN
		CPoint mouse;
		GetCursorPos(&mouse);
		::SetForegroundWindow( m_nid.hWnd);
		::TrackPopupMenu (pSubMenu->m_hMenu, 0, mouse.x, mouse.y, 0, m_nid.hWnd, NULL);
	}else
	{
		// Double click: execute first menu item
//		::SendMessage( m_nid.hWnd, WM_COMMAND, pSubMenu->GetMenuItemID(0), 0);
		ShowWindow(m_nid.hWnd, SW_SHOW);
	}

	return 1; // Handled
}